package com.thero.core.controller;

import com.thero.core.chess.Message;
import com.thero.core.chess.Room;
import com.thero.core.command.CommandHandler;
import com.thero.core.command.MatchInformation;
import com.thero.core.command.RivalMatcher;
import com.thero.core.command.annotation.Controller;
import com.thero.core.command.annotation.Handler;
import com.thero.core.command.cmd.*;
import com.thero.core.net.ClientChannel;
import com.thero.core.net.ProtocolMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * Created by wusk on 2017/11/30.
 * 通用控制器，命令字处理器。
 * 命令字处理器类必须用@Controller注解，处理方法必须用@Handler注解；
 * 方法参数只能是ProtocolMessage
 * 方法返回值只能是Command或其实现类
 */
@Controller
public class CommonController {
    private static final Logger logger = LoggerFactory.getLogger(CommonController.class);

    /**
     * 心跳包
     * @param context 上下文
     * @param message 消息
     */
    @Handler(code = 1010)
    public void heartbeat(CommandHandler context, ProtocolMessage message){

    }

    /**
     * 匹配请求
     * @param context 游戏信息
     * @param message 请求消息
     */
    @Handler(code = 2000)
    public void playerMatch(CommandHandler context, ProtocolMessage message){
        try{
            MatchCommand cmd = new MatchCommand(message);
            MatchInformation info = new MatchInformation();
            info.setHome(cmd.getHome());
            info.setPlayerId(cmd.getPlayerId());
            RivalMatcher matcher = context.getMatcher();
            Room room = matcher.match(info);
            if(null == room){
                ProtocolMessage[] messages = ProtocolMessage.newMessage((short)2500, message.getMessage());
                ClientChannel channel = context.getChannel(info.getHome());
                if(null == channel){
                    logger.error("Get channel with null. home = {}", info.getHome());
                }else{
                    channel.send(messages);
                }
            }else{
                //先把新建的房间放到大厅中
                context.putRoom(room);
                sendResponse(context, room.getMessages());
            }
        }catch (Exception e){
            logger.error("", e);
        }
    }

    /**
     * 落子消息
     * @param context 游戏信息
     * @param message 请求消息
     */
    @Handler(code = 3000)
    public void playerPut(CommandHandler context, ProtocolMessage message){
        try {
            PutPiece put = new PutPiece(message);
            Room room = context.getRoom(put.getRoomId());
            if(null == room){
                logger.error("Wrong room id, can not find room with id: {}", put.getRoomId());
                return;
            }
            if(!room.playerCheck(put.getPlayerId())){
                logger.error("Wrong player id, can not find player in room. room id = {}, player id = {}", put.getRoomId(), put.getPlayerId());
                return;
            }
            room.put(put);
            sendResponse(context, room.getMessages());
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    /**
     * 玩家走子
     * @param context 环境信息
     * @param message 消息
     */
    @Handler(code = 4000)
    public void playerMove(CommandHandler context, ProtocolMessage message){
        try {
            MovePiece move = new MovePiece(message);
            Room room = context.getRoom(move.getRoomId());
            if(null == room){
                logger.error("Wrong room id, can not find room with id: {}", move.getRoomId());
                return;
            }
            if(!room.playerCheck(move.getPlayerId())){
                logger.error("Wrong player id, can not find player in room. room id = {}, player id = {}", move.getRoomId(), move.getPlayerId());
                return;
            }
            room.move(move);
            sendResponse(context, room.getMessages());
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    /**
     * 玩家吃子
     * @param context 环境信息
     * @param message 消息
     */
    @Handler(code = 5000)
    public void playerKill(CommandHandler context, ProtocolMessage message){
        try {
            KillPiece kill = new KillPiece(message);
            Room room = context.getRoom(kill.getRoomId());
            if(null == room){
                logger.error("Wrong room id, can not find room with id: {}", kill.getRoomId());
                return;
            }
            if(!room.playerCheck(kill.getPlayerId())){
                logger.error("Wrong player id, can not find player in room. room id = {}, player id = {}", kill.getRoomId(), kill.getPlayerId());
                return;
            }
            room.kill(kill);
            sendResponse(context, room.getMessages());
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    /**
     * 发送响应
     * @param context 共享信息
     * @param list 房间的消息列表。
     */
    private void sendResponse(CommandHandler context, List<Message> list){
        for(Message message: list){
            ClientChannel channel = context.getChannel(message.getHome());
            ProtocolMessage[] messages = ProtocolMessage.newMessage(message);
            channel.send(messages);
        }
        //因为对游戏房间的处理是单线程的，所以可以直接清空
        list.clear();
    }
}
